home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
programming
/
other
/
jikes
/
src
/
incrmnt.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
15KB
|
410 lines
// $Id: incrmnt.cpp,v 1.6 1999/03/10 19:59:21 shields Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://www.ibm.com/research/jikes.
// Copyright (C) 1996, 1998, International Business Machines Corporation
// and others. All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
#include "config.h"
#include <sys/stat.h>
#include <iostream.h>
#include "bool.h"
#include "control.h"
#include "scanner.h"
#include "parser.h"
#include "semantic.h"
#include "unicode.h"
#include "set.h"
void Control::RemoveTrashedTypes(SymbolSet &type_trash_set)
{
TypeSymbol *type;
//
// For each type T that is going to be trashed, and for each parent P of T that
// is not itself being trashed, remove T from the set of dependents of P.
// If T is a subtype of P it is also removed from the subtypes set.
//
for (type = (TypeSymbol *) type_trash_set.FirstElement(); type; type = (TypeSymbol *) type_trash_set.NextElement())
{
for (TypeSymbol *parent = (TypeSymbol *) type -> parents -> FirstElement();
parent;
parent = (TypeSymbol *) type -> parents -> NextElement())
{
if (! type_trash_set.IsElement(parent))
{
parent -> dependents -> RemoveElement(type);
parent -> subtypes -> RemoveElement(type);
}
}
}
//
// We can now safely delete the type.
//
for (type = (TypeSymbol *) type_trash_set.FirstElement(); type; type = (TypeSymbol *) type_trash_set.NextElement())
{
PackageSymbol *package = type -> ContainingPackage();
//
// If a type that is about to be trashed was read in via a class file, remove the class file.
// Note that invoking RemoveElement for a file that it does not contain has no ill effect.
//
FileSymbol *file_symbol = type -> file_symbol;
if (file_symbol && type -> Identity() == file_symbol -> Identity())
input_class_file_set.RemoveElement(file_symbol);
//
// If a type that is about to be trashed was contained in the unnamed_package,
// remove it from the set "unnamed_package_types"
//
if (package == unnamed_package)
unnamed_package_types.RemoveElement(type);
//
// Remove the type from its containing package.
//
package -> DeleteTypeSymbol(type);
}
return;
}
inline DirectoryEntry *Control::FindInputFile(FileSymbol *file_symbol)
{
int length = file_symbol -> Utf8NameLength() + FileSymbol::java_suffix_length;
char *java_name = new char[length + 1]; // +1 for '\0'
strcpy(java_name, file_symbol -> Utf8Name());
strcat(java_name, FileSymbol::java_suffix);
DirectoryEntry *java_entry = file_symbol -> directory_symbol -> FindEntry(java_name, length);
delete [] java_name;
return java_entry;
}
//
// For each file whose associated source (".java") has changed, add it to the list to be recompiled...
//
void Control::FindMoreRecentInputFiles(SymbolSet &file_candidates)
{
for (FileSymbol *file_symbol = (FileSymbol *) file_candidates.FirstElement();
file_symbol;
file_symbol = (FileSymbol *) file_candidates.NextElement())
{
//
// If the type is not zipped and it is not already contained in the recompilation set, then check it...
//
if ((! file_symbol -> IsZip()) &&
(! recompilation_file_set.IsElement(file_symbol)) &&
(! expired_file_set.IsElement(file_symbol)))
{
//
// If there is no java source file or its time stamp is not newer than file_symbol then
// reset file_symbol to NULL. Otherwise, reset file symbol to the newer file.
//
DirectoryEntry *java_entry = FindInputFile(file_symbol);
if (! java_entry)
{
if (file_symbol -> IsJava()) // A source file that was compiled in the previous pass no longer exists.
expired_file_set.AddElement(file_symbol);
}
else if (java_entry -> Mtime() > file_symbol -> mtime) // a newer file was found
{
file_symbol -> mtime = java_entry -> Mtime();
recompilation_file_set.AddElement(file_symbol);
}
}
}
return;
}
void Control::RereadDirectory(DirectorySymbol *directory_symbol)
{
directory_symbol -> ResetDirectory();
for (int i = 0; i < directory_symbol -> subdirectories.Length(); i++)
RereadDirectory(directory_symbol -> subdirectories[i]);
return;
}
void Control::RereadDirectories()
{
for (int i = (dot_classpath_index == 0 ? 0 : 1); i < classpath.Length(); i++)
{
PathSymbol *path_symbol = classpath[i];
if (! path_symbol -> IsZip())
RereadDirectory(path_symbol -> RootDirectory());
}
return;
}
void Control::ComputeRecompilationSet(TypeDependenceChecker &dependence_checker)
{
SymbolSet type_trash_set;
//
// Find out if any source files has been touched since the last compilation and
// add all such files to recompilation_file_set.
//
FindMoreRecentInputFiles(dependence_checker.file_set);
//
// Before messing with the files, compute a list of all the types that have just been compiled.
// We need to do this here as we will be "Resetting" and "reScanning" some files in the loop below,
// which in effect removes the set of types to which they were associated in the previous compilation.
//
int length_estimate = input_java_file_set.Size(); // an estimate of the size of the problem
Tuple<TypeSymbol *> input_types(length_estimate * 2);
for (FileSymbol *file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
file_symbol;
file_symbol = (FileSymbol *) input_java_file_set.NextElement())
{
for (int i = 0; i < file_symbol -> types.Length(); i++)
input_types.Next() = file_symbol -> types[i];
}
//
// Declare the closure set, and initialize it with the Union over the closure of the
// types in the trash_bin. Essentially, we want to catch all "compiled" types in the
// compilation that has a dependence on these bad types.
//
SymbolSet dependents_closure(length_estimate);
for (int i = 0; i < type_trash_bin.Length(); i++)
{
TypeSymbol *type = type_trash_bin[i];
if (! dependents_closure.IsElement(type))
{
if (type -> dependents_closure)
dependents_closure.Union(*(type -> dependents_closure));
else dependents_closure.AddElement(type);
}
}
//
// Compute the set of types from the recompilation set that needs to be recompiled
// and update the recompilation file set.
//
SymbolSet new_set(length_estimate),
file_seen(length_estimate);
new_set = recompilation_file_set;
new_set.Union(expired_file_set);
file_seen = new_set;
StoragePool *ast_pool = new StoragePool(64); // how much space do we need for a package declaration? estimate 64 tokens.
//
// As long as there is a new_set of files to process,...
//
do
{
//
// For each file in new_set, compute the reflexive transitive closure of all types contained in that file.
// Next, reset and rescan the file. If the scan was successful, iterate over the new list of types to see
// if any of them had already been introduced in the previous compilation via a class file. If so, add all such
// types to the dependents closure.
//
for (FileSymbol *file_symbol = (FileSymbol *) new_set.FirstElement();
file_symbol;
file_symbol = (FileSymbol *) new_set.NextElement())
{
for (int i = 0; i < file_symbol -> types.Length(); i++)
{
TypeSymbol *type = file_symbol -> types[